package com.ums.upos.service;

import android.content.Context;
import android.media.SoundPool;
import android.os.Build;
import android.os.RemoteException;

import com.ums.upos.GlobalDataHolder;
import com.ums.upos.uapi.R;
import com.ums.upos.uapi.device.beeper.BeepModeConstrants;
import com.ums.upos.uapi.device.beeper.Beeper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import rx.Observable;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

/**
 * 蜂鸣器服务类
 */
public class BeeperBinder extends Beeper.Stub {
    private Logger log;
    private final String TAG = "Beeper";
    private com.nexgo.oaf.apiv3.device.beeper.Beeper sdkBeeper;
    private boolean isBeepEnable = true;
    private SoundPool sp;
    Map<String, Integer> audioMap;
    private Context mContext;
    private int mLoadedCnt = 0;
    private boolean isLoaded = false;

    public BeeperBinder(Context context) {
        log = LoggerFactory.getLogger(TAG);
        mContext = context;
        if (Build.MODEL.equals("N3")) {
//        if(true){
            isBeepEnable = false;
            SoundPool.Builder spb = new SoundPool.Builder();
            spb.setMaxStreams(10);
//            spb.setAudioAttributes(null);
            sp = spb.build();
            audioMap = new HashMap<String, Integer>();
            audioMap.put("SUCCESS", sp.load(mContext, R.raw.beepok, 1));
            audioMap.put("FAIL", sp.load(mContext, R.raw.beepfail, 1));
            audioMap.put("INTERVAL", sp.load(mContext, R.raw.beepinterval, 1));
            audioMap.put("ERROR", sp.load(mContext, R.raw.beeperr, 1));
            sp.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
                @Override
                public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
                    mLoadedCnt++;
                    if(mLoadedCnt == 4){
                        isLoaded = true;
                        log.debug("soundpool allloaded!");
                    }
    //                int rslt = soundPool.play(audioMap.get("SUCCESS"), 1, 1, 0, 0, 1);
    //                log.debug("sp.play onLoadComplete rslt:{}", rslt);
                }
            });
        }
        else
            sdkBeeper = GlobalDataHolder.getInstance().getDeviceEngine().getBeeper();
    }

    private void play(final String audioname) {
//        sp.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
//            @Override
//            public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
//                int rslt = soundPool.play(audioMap.get(audioname), 1, 1, 0, 0, 1);
//                log.debug("sp.play rslt:{}", rslt);
//            }
//        });
        while (!isLoaded) {
            try {
                Thread.sleep(100, 0);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        int rslt = sp.play(audioMap.get(audioname), 1, 1, 0, 0, 1);
        log.debug("sp.play rslt:{}", rslt);
    }

    @Override
    public void beep(int mode) throws RemoteException {
        log.info("call beep {}", mode);
        if (mode != BeepModeConstrants.NORMAL
                && mode != BeepModeConstrants.SUCCESS
                && mode != BeepModeConstrants.FAIL
                && mode != BeepModeConstrants.INTERVAL
                && mode != BeepModeConstrants.ERROR) {
            mode = BeepModeConstrants.NORMAL;
        }
        switch (mode) {
            case BeepModeConstrants.NORMAL:
                Observable.just(null)
                        .observeOn(Schedulers.io())
                        .subscribe(new Action1<Object>() {
                            @Override
                            public void call(Object o) {
                                if (isBeepEnable)
                                    sdkBeeper.beep(100);
                                else
                                    play("SUCCESS");
                            }
                        }, new Action1<Throwable>() {
                            @Override
                            public void call(Throwable throwable) {

                            }
                        });
                break;
            case BeepModeConstrants.SUCCESS:
                Observable.just(null)
                        .observeOn(Schedulers.io())
                        .subscribe(new Action1<Object>() {
                            @Override
                            public void call(Object o) {
                                if (isBeepEnable)
                                    sdkBeeper.beep(500);
                                else
                                    play("SUCCESS");
                            }
                        }, new Action1<Throwable>() {
                            @Override
                            public void call(Throwable throwable) {

                            }
                        });
                break;
            case BeepModeConstrants.FAIL:
                if (!isBeepEnable) {
                    Observable.just(null)
                            .observeOn(Schedulers.io())
                            .subscribe(new Action1<Object>() {
                                @Override
                                public void call(Object o) {
                                    play("FAIL");
                                }
                            });
                    break;
                }
                Observable.interval(70, TimeUnit.MILLISECONDS)
                        .observeOn(Schedulers.io())
                        .takeUntil(new Func1<Long, Boolean>() {
                            @Override
                            public Boolean call(Long aLong) {
                                return aLong == 1;
                            }
                        })
                        .subscribe(new Action1<Object>() {
                            @Override
                            public void call(Object o) {
                                sdkBeeper.beep(50);
                            }
                        }, new Action1<Throwable>() {
                            @Override
                            public void call(Throwable throwable) {

                            }
                        });
                break;
            case BeepModeConstrants.INTERVAL:
                if (!isBeepEnable) {
                    Observable.just(null)
                            .observeOn(Schedulers.io())
                            .subscribe(new Action1<Object>() {
                                @Override
                                public void call(Object o) {
                                    play("INTERVAL");
                                }
                            });
                    break;
                }
                Observable.interval(600, TimeUnit.MILLISECONDS)
                        .observeOn(Schedulers.io())
                        .takeUntil(new Func1<Long, Boolean>() {
                            @Override
                            public Boolean call(Long aLong) {
                                if (isBeepEnable)
                                    return aLong == 3;
                                else
                                    return aLong == 1;
                            }
                        })
                        .subscribe(new Action1<Object>() {
                            @Override
                            public void call(Object o) {
                                if (isBeepEnable)
                                    sdkBeeper.beep(100);
                                else
                                    play("INTERVAL");
                            }
                        }, new Action1<Throwable>() {
                            @Override
                            public void call(Throwable throwable) {

                            }
                        });
                break;
            case BeepModeConstrants.ERROR:
                if (!isBeepEnable) {
                    Observable.just(null)
                            .observeOn(Schedulers.io())
                            .subscribe(new Action1<Object>() {
                                @Override
                                public void call(Object o) {
                                    if (isBeepEnable)
                                        sdkBeeper.beep(100);
                                    else
                                        play("ERROR");
                                }
                            });
                    break;
                }
                Observable.interval(400, TimeUnit.MILLISECONDS)
                        .observeOn(Schedulers.io())
                        .takeUntil(new Func1<Long, Boolean>() {
                            @Override
                            public Boolean call(Long aLong) {
                                if (isBeepEnable)
                                    return aLong == 2;
                                else
                                    return aLong == 1;
                            }
                        })
                        .subscribe(new Action1<Object>() {
                            @Override
                            public void call(Object o) {
                                if (isBeepEnable)
                                    sdkBeeper.beep(200);
                                else
                                    play("ERROR");
                            }
                        }, new Action1<Throwable>() {
                            @Override
                            public void call(Throwable throwable) {

                            }
                        });
                break;
        }
    }
}
